package com.ktjiaoyu.travelaiagent.tools;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpUtil;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.html2pdf.ConverterProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.model.ToolContext;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.File;
import java.net.URL;
import java.nio.file.Paths;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Component
@Slf4j
public class PdfGenerateTool {

    // 文件根目录
    @Value("${travel.ai.files.root}")
    private String fileRoot;

    /**
     * 生成PDF文件工具方法
     *
     * @param fileName    PDF文件名
     * @param type        文本类型（支持：text、markdown、html三种格式）
     * @param content     文本内容或文件路径
     * @param toolContext 工具上下文，用于获取会话ID等信息
     * @return 生成结果信息，包含最终文件名
     */
    @Tool(description = "Generate a PDF file from text, markdown or HTML content. 可用于生成旅游报告，只允许引用图片资源，可通过markdown和html生成图文并茂的PDF报告，资源需先通过下载工具DownloadTool下载到指定目录通过相对路径进行引用。")
    public String generatePdf(
            @ToolParam(description = "PDF file name", required = true) String fileName,
            @ToolParam(description = "Text type (support: text, markdown, html)", required = true) String type,
            @ToolParam(description = "Text content or file path", required = true) String content,
            ToolContext toolContext) {
        
        // 获取会话ID用于文件隔离
        String chatId = (String) toolContext.getContext().get("chatId");
        log.info("AI调用generatePdf工具生成PDF，文件名: {}, 类型: {}, chatId: {}", fileName, type, chatId);
        
        if (chatId == null) {
            chatId = "";
        } else {
            chatId = chatId + "/"; // 拼接路径分割
        }
        
        try {
            // 生成带时间戳的PDF文件名
            String timestamp = String.valueOf(System.currentTimeMillis());
            String pdfFileName = fileName.replaceAll("\\.pdf$", "") + "_" + timestamp + ".pdf";
            String filePath = this.fileRoot + "/" + chatId + pdfFileName;
            
            // 创建父目录（如果不存在）
            FileUtil.mkParentDirs(filePath);
            
            // 根据类型生成PDF
            if ("text".equalsIgnoreCase(type)) {
                generatePdfFromText(content, filePath);
            } else if ("markdown".equalsIgnoreCase(type)) {
                // 处理Markdown中的图片资源
                String processedContent = processMarkdownImages(content, chatId);
                generatePdfFromMarkdown(processedContent, filePath);
            } else if ("html".equalsIgnoreCase(type)) {
                // 处理HTML中的图片资源
                String processedContent = processHtmlImages(content, chatId);
                generatePdfFromHtml(processedContent, filePath);
            } else {
                throw new IllegalArgumentException("不支持的文本类型: " + type + "，仅支持text、markdown、html格式");
            }
            
            log.info("AI调用generatePdf工具生成PDF成功: {}", filePath);
            return pdfFileName;
        } catch (Exception e) {
            log.error("AI调用generatePdf工具生成PDF出现异常: {}", e.getMessage(), e);
            return "生成PDF文件时出现错误: " + e.getMessage();
        }
    }

    /**
     * 处理Markdown中的图片资源
     *
     * @param markdownContent Markdown内容
     * @param chatId          会话ID
     * @return 处理后的Markdown内容
     */
    private String processMarkdownImages(String markdownContent, String chatId) {
        // 匹配Markdown图片语法 ![alt](src)
        Pattern imagePattern = Pattern.compile("!\\[(.*?)\\]\\((.*?)\\)");
        Matcher matcher = imagePattern.matcher(markdownContent);
        StringBuffer sb = new StringBuffer();
        
        while (matcher.find()) {
            String altText = matcher.group(1);
            String imagePath = matcher.group(2);
            
            // 处理图片路径
            String processedImagePath = processImagePath(imagePath, chatId);
            
            // 如果处理后的路径为空，跳过该图片
            if (processedImagePath.isEmpty()) {
                matcher.appendReplacement(sb, "");
            } else {
                matcher.appendReplacement(sb, "![" + altText + "](" + processedImagePath + ")");
            }
        }
        matcher.appendTail(sb);
        
        return sb.toString();
    }

    /**
     * 处理HTML中的图片资源
     *
     * @param htmlContent HTML内容
     * @param chatId      会话ID
     * @return 处理后的HTML内容
     */
    private String processHtmlImages(String htmlContent, String chatId) {
        // 匹配HTML img标签的src属性
        Pattern imagePattern = Pattern.compile("<img[^>]*src\\s*=\\s*[\"']([^\"']*)[\"'][^>]*/?>", Pattern.CASE_INSENSITIVE);
        Matcher matcher = imagePattern.matcher(htmlContent);
        StringBuffer sb = new StringBuffer();
        
        while (matcher.find()) {
            String imgTag = matcher.group(0);
            String imagePath = matcher.group(1);
            
            // 处理图片路径
            String processedImagePath = processImagePath(imagePath, chatId);
            
            // 如果处理后的路径为空，跳过该图片
            if (processedImagePath.isEmpty()) {
                matcher.appendReplacement(sb, "");
            } else {
                // 替换img标签中的src属性
                String processedImgTag = imgTag.replaceAll("src\\s*=\\s*[\"']" + Pattern.quote(imagePath) + "[\"']", 
                                                           "src=\"" + processedImagePath + "\"");
                matcher.appendReplacement(sb, processedImgTag);
            }
        }
        matcher.appendTail(sb);
        
        return sb.toString();
    }

    /**
     * 处理图片路径，支持相对路径和网络地址
     *
     * @param imagePath 图片路径
     * @param chatId    会话ID
     * @return 处理后的图片路径
     */
    private String processImagePath(String imagePath, String chatId) {
        // 如果是网络地址，下载图片
        if (isHttpUrl(imagePath)) {
            log.info("检测到网络图片资源，开始下载: {}", imagePath);
            try {
                // 生成唯一文件名
                String fileExtension = ".jpg"; // 默认扩展名
                int lastDotIndex = imagePath.lastIndexOf('.');
                if (lastDotIndex > 0) {
                    fileExtension = imagePath.substring(lastDotIndex);
                }
                
                String uniqueFileName = "image_" + System.currentTimeMillis() + "_" + 
                                       Math.abs(imagePath.hashCode()) + fileExtension;
                String imageFilePath = this.fileRoot + "/" + chatId + uniqueFileName;
                
                // 创建父目录（如果不存在）
                FileUtil.mkParentDirs(imageFilePath);
                
                // 下载图片
                HttpUtil.downloadFile(imagePath, imageFilePath);
                log.info("网络图片资源下载完成: {} -> {}", imagePath, imageFilePath);
                
                // 返回相对于PDF文件的路径
                return uniqueFileName;
            } catch (Exception e) {
                log.error("下载网络图片资源失败: {}", e.getMessage(), e);
                return imagePath; // 下载失败则直接使用原路径
            }
        }
        
        // 如果是相对路径，检查文件是否存在
        String fullPath = this.fileRoot + "/" + chatId + imagePath;
        File imageFile = new File(fullPath);
        if (imageFile.exists() && imageFile.isFile()) {
            log.info("检测到本地图片资源: {}", fullPath);
            return imagePath; // 相对路径可以直接使用
        }
        
        // 如果路径无效，返回空字符串以跳过该图片
        if (imagePath == null || imagePath.trim().isEmpty()) {
            log.warn("图片路径为空，跳过该图片");
            return "";
        }
        
        // 其他情况直接返回原路径
        log.warn("未找到图片资源，使用原始路径: {}", imagePath);
        return imagePath;
    }

    /**
     * 判断是否为HTTP或HTTPS URL
     *
     * @param url URL字符串
     * @return 是否为HTTP或HTTPS URL
     */
    private boolean isHttpUrl(String url) {
        try {
            URL parsedUrl = URLUtil.url(url);
            String protocol = parsedUrl.getProtocol();
            return "http".equalsIgnoreCase(protocol) || "https".equalsIgnoreCase(protocol);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 从文本生成PDF
     *
     * @param content  文本内容
     * @param filePath 生成的PDF文件路径
     * @throws Exception 生成过程中可能抛出的异常
     */
    private void generatePdfFromText(String content, String filePath) throws Exception {
        PdfWriter writer = new PdfWriter(filePath);
        PdfDocument pdf = new PdfDocument(writer);
        Document document = new Document(pdf);
        
        // 添加内容到PDF，使用系统默认字体支持中文
        Paragraph paragraph = new Paragraph(content);
        // 为纯文本PDF设置字体以支持中文显示
        // 使用STSongStd-Light字体确保中文字体支持
        PdfFont font = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H");
        document.setFont(font);
        document.add(paragraph);
        
        // 关闭文档
        document.close();
    }

    /**
     * 从Markdown生成PDF（转换为HTML后再生成PDF）
     *
     * @param markdownContent Markdown内容
     * @param filePath        生成的PDF文件路径
     * @throws Exception 生成过程中可能抛出的异常
     */
    private void generatePdfFromMarkdown(String markdownContent, String filePath) throws Exception {
        // 简单的Markdown到HTML转换（实际项目中可能需要更复杂的转换）
        String htmlContent = convertMarkdownToHtml(markdownContent);
        // 使用iText的HtmlConverter生成PDF，支持中文字体
        ConverterProperties properties = new ConverterProperties();
        DefaultFontProvider fontProvider = new DefaultFontProvider(true, true, true);
        properties.setFontProvider(fontProvider);

        // 设置基路径以便正确解析相对路径图片
        File pdfFile = new File(filePath);
        properties.setBaseUri(pdfFile.getParentFile().toURI().toString());
        
        HtmlConverter.convertToPdf(htmlContent, new PdfWriter(filePath), properties);
    }

    /**
     * 从HTML生成PDF
     *
     * @param htmlContent HTML内容
     * @param filePath    生成的PDF文件路径
     * @throws Exception 生成过程中可能抛出的异常
     */
    private void generatePdfFromHtml(String htmlContent, String filePath) throws Exception {
        // 使用iText的HtmlConverter生成PDF，支持中文字体
        ConverterProperties properties = new ConverterProperties();
        DefaultFontProvider fontProvider = new DefaultFontProvider(true, true, true);
        properties.setFontProvider(fontProvider);
        
        // 设置基路径以便正确解析相对路径图片
        File pdfFile = new File(filePath);
        properties.setBaseUri(pdfFile.getParentFile().toURI().toString());
        
        HtmlConverter.convertToPdf(htmlContent, new PdfWriter(filePath), properties);
    }

    /**
     * 简单的Markdown到HTML转换
     *
     * @param markdown Markdown内容
     * @return 转换后的HTML
     */
    private String convertMarkdownToHtml(String markdown) {
        // 这里实现一个简单的Markdown到HTML转换
        // 实际项目中建议使用专门的Markdown解析库
        
        String html = markdown;
        
        // 替换Markdown标题
        html = html
                .replaceAll("(?m)^#\\s+(.*)", "<h1>$1</h1>")
                .replaceAll("(?m)^##\\s+(.*)", "<h2>$1</h2>")
                .replaceAll("(?m)^###\\s+(.*)", "<h3>$1</h3>")
                .replaceAll("(?m)^####\\s+(.*)", "<h4>$1</h4>")
                .replaceAll("(?m)^#####\\s+(.*)", "<h5>$1</h5>")
                .replaceAll("(?m)^######\\s+(.*)", "<h6>$1</h6>");
        
        // 处理图片，避免图片URL中的格式标记被提前处理
        html = html.replaceAll("!\\[(.*?)\\]\\((.*?)\\)", "<img src=\"$2\" alt=\"$1\" />");
        
        // 替换粗体和斜体，使用负向先行断言排除已经在HTML标签内的内容
        // 匹配不在HTML标签内的**粗体**
        html = html.replaceAll("\\*\\*(?![^<]*>)(.*?)\\*\\*", "<strong>$1</strong>");
        // 匹配不在HTML标签内的*斜体*
        html = html.replaceAll("\\*(?![^<]*>)(.*?)\\*", "<em>$1</em>");
        // 匹配不在HTML标签内的__粗体__
        html = html.replaceAll("__(?![^<]*>)(.*?)__", "<strong>$1</strong>");
        // 匹配不在HTML标签内的_斜体_
        html = html.replaceAll("_(?![^<]*>)(.*?)_", "<em>$1</em>");
        
        // 替换代码块
        html = html.replaceAll("(?s)```(.*?)```", "<pre><code>$1</code></pre>")
                .replaceAll("(?m)^>\\s+(.*)", "<blockquote>$1</blockquote>");
        
        // 替换列表
        html = html.replaceAll("(?m)^\\*\\s+(.*)", "<li>$1</li>")
                .replaceAll("(?m)^\\d+\\.\\s+(.*)", "<li>$1</li>");
        
        // 包装在基本HTML结构中，设置基础样式以支持图片显示和支持中文字体
        html = "<!DOCTYPE html><html><head><meta charset='UTF-8'>" +
               "<style>img { max-width: 100%; height: auto; }</style>" +
               "</head><body>" + html + "</body></html>";
        
        return html;
    }
}